#pragma once
#ifndef OBR_CUDAMODULE_H
#define OBR_CUDAMODULE_H

#include "common.h"
#include "helpers/Helpers.h"

namespace OBR
{
class CudaModule
{
private:
    static std::map<std::string, std::shared_ptr<CudaModule>> mapping;

public:
    bool ready = false;
    std::string cuda_source_path;
    std::string compiled_ptx;
    OptixModuleCompileOptions module_compile_options = {};
    OptixModule optix_module;

private:
    /**
     * @brief compile source code @ this->cuda_source_path
     *
     * @return success or fail
     */
    bool compile();

public:
    CudaModule(std::string _cuda_source_path = "");
    ~CudaModule();

    /**
     * @brief link from ptx to module using given context and pipeline compile options
     *
     * @param ctx
     * @param pipeline_compile_options
     * @return success or fail
     */
    bool link(OptixDeviceContext &ctx, OptixPipelineCompileOptions &pipeline_compile_options);

public:
    static std::shared_ptr<CudaModule> addModule(std::string _cuda_source_path);

    static std::shared_ptr<CudaModule> getModule(std::string _cuda_source_path);

    static void linkAllModules(OptixDeviceContext &ctx,
                               OptixPipelineCompileOptions &pipeline_compile_options);
};
} // namespace OBR

#endif